package com.techgene.kanban.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.techgene.kanban.dao.ProjectDao;
import com.techgene.kanban.domain.Project;
import com.techgene.kanban.domain.User;
import com.techgene.kanban.exception.KBDaoException;
import com.techgene.kanban.exception.KBServiceException;
import com.techgene.kanban.service.ProjectService;
import com.techgene.kanban.util.AppConstants;

@Service
public class ProjectServiceImpl implements ProjectService {

	private Logger logger = LoggerFactory.getLogger(ProjectServiceImpl.class);

	@Autowired
	private PlatformTransactionManager txManager;
	@Autowired
	ProjectDao projectDao;

	
	
	/**
	 * retriveing users
	 * 
	 * @param searchText  String
	 * @return
	 * @throws KBServiceException
	 * @throws KBDaoException
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List retrieveUsers(String searchText, List totalSelectedUsers)
			throws KBServiceException, KBDaoException {

		logger.debug(" >> retrieveUsers , [ searchText = {} ] ", searchText);
		TransactionDefinition def = new DefaultTransactionDefinition();
		TransactionStatus status = txManager.getTransaction(def);
		List usersList;
		List selectedUsernames = new ArrayList<String>();
		try {

				for (int i = 0; i < totalSelectedUsers.size(); i++) {
					User user = (User) totalSelectedUsers.get(i);
					selectedUsernames.add(user.getUsername());
			}

			usersList = projectDao.retrieveUsers(searchText, selectedUsernames);
			logger.debug(" usersList = {} ", usersList);
			/* commit */
			txManager.commit(status);

		} catch (KBDaoException e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(e.getErrorCode(), e.getMessage(), e);

		} catch (Exception e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.msg,e);

		} catch (Throwable e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.msg,e);

		}

		logger.debug(" << retriveUsers , [ usersList = {} ] ", usersList);
		return usersList;
	}

	
	
	
	/**
	 * adding project
	 * @param projectName String
	 * @param projectDescription String
	 * @param selectedUsers List
	 * @param int projectID
	 * @throws KBServiceException
	 * @throws KBDaoException
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public int addOrUpdateProject(String projectName, String projectDescription,
			List selectedUsers,String type,int projectId) throws KBServiceException, KBDaoException {

		logger.debug(" >> addProject [ projectName = {}, projectDescription = {} , selectedUsers = {} , projectId = {}  ]",projectName, projectDescription, selectedUsers,projectId);
		TransactionDefinition def = new DefaultTransactionDefinition();
		TransactionStatus status = txManager.getTransaction(def);
		List usernames = new ArrayList();
		int result;
		
		for (int i = 0; i < selectedUsers.size(); i++) {
			
			User user = (User) selectedUsers.get(i);
			usernames.add(user.getUsername());
		}
		try {
			/* calling addproject */
			result = projectDao.addOrUpdateProject(projectName, projectDescription,usernames,type,projectId);
			txManager.commit(status);

		} catch (KBDaoException e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(e.getErrorCode(), e.getMessage(), e);

		} catch (Exception e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(
					AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.code,
					AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.msg,
					e);

		} catch (Throwable e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(
					AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.code,
					AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_ADD_PROJECT_DETAILS.msg,
					e);

		}
		
		logger.debug(" << addProject [result = {} ]",result);
		return result;
	}
	
	
	
	
	/**
	 * fetching projects list
	 * @return projects
	 */
	@SuppressWarnings("unchecked")
	public List<Project> listProjects() throws KBServiceException,KBDaoException {

		List<Project> projects = new ArrayList<Project>();
		TransactionDefinition def = new DefaultTransactionDefinition();
		TransactionStatus status = txManager.getTransaction(def);

		try {

			/*
			 * calling listAllProjectNames to retrieve all projects
			 */
			projects = projectDao.listProjects();
			logger.debug(" project list:[{}]", projects);
			txManager.commit(status);

		} catch (KBDaoException e) {
			
			txManager.rollback(status);
			throw new KBServiceException(e.getErrorCode(), e.getMessage(), e);

		} catch (Exception e) {
			
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_LIST_PROJECT.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_LIST_PROJECT.msg,e);

		} catch (Throwable e) {
			
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_LIST_PROJECT.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_LIST_PROJECT.msg,e);

		}

		logger.debug(" << fetch list of Projects");
		return projects;

	}
	
	
	
	
	/**
	 * deleting project
	 * @param projectName String
	 * @return
	 */
	public int deleteProject(String projectName) throws KBDaoException,KBServiceException{
		
		logger.debug(" >> deleteProject [projectName = {} ]" , projectName);
		int result=0;
		/* start of transaction */
		TransactionDefinition def = new DefaultTransactionDefinition();
		TransactionStatus status = txManager.getTransaction(def);
		
		try
		{
			/* calling delete project */
			result=projectDao.deleteProject(projectName);
			logger.debug("result = {} " , result);
			/* commit */
			txManager.commit(status);
			
		}catch (KBDaoException e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(e.getErrorCode(), e.getMessage(), e);

		} catch (Exception e) {
			
			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.msg,e);

		} catch (Throwable e) {
			
			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.msg,e);

		}
		
		logger.debug(" << deleteProject [ result = {} ]" , result);
		return result;
	}
	

	
	
	/**
	 * retrieving users for the project
	 * @param projectName String
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public Map retrieveUsersOfProject(String projectName) throws KBDaoException,KBServiceException{
		
		logger.debug(" >> retrieveUsersOfProject [ projectName = {} ]" , projectName);
		/* start of transaction */
		TransactionDefinition def = new DefaultTransactionDefinition();
		TransactionStatus status = txManager.getTransaction(def);
		Map project;
		try{
			
			/* retrieving users */
			project = projectDao.retrieveUsersOfProject(projectName);
			logger.debug(" project =  {} ",project);
			/* commit */
			txManager.commit(status);
			
		}catch (KBDaoException e) {

			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(e.getErrorCode(), e.getMessage(), e);

		} catch (Exception e) {
			
			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.msg,e);

		} catch (Throwable e) {
			
			/* rollback */
			txManager.rollback(status);
			throw new KBServiceException(AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.code,AppConstants.ERROR.SERVICE_UNKNOWN_ERROR_DELETE_PROJECT.msg,e);

		}
		
		logger.debug(" << retrieveUsersOfProject [ project = {} ] " , project);
		return project;
		
	}
}
